package com.zjsru.plan2024.oneday;

import java.util.HashMap;
import java.util.Map;

/**
 * 3242. 设计相邻元素求和服务
 *
 * @Author: cookLee
 * @Date: 2024-11-09
 */
public class NeighborSum {

    /**
     * 主
     * \
     * ["neighborSum", "adjacentSum", "adjacentSum", "diagonalSum", "diagonalSum"]
     * [[[[0, 1, 2], [3, 4, 5], [6, 7, 8]]], [1], [4], [4], [8]]
     * 输出： [null, 6, 16, 16, 4]
     * \
     * ["neighborSum", "adjacentSum", "diagonalSum"]
     * [[[[1, 2, 0, 3], [4, 7, 15, 6], [8, 9, 10, 11], [12, 13, 14, 5]]], [15], [9]]
     * 输出： [null, 23, 45]
     * \
     *
     * @param args args
     */
    public static void main(String[] args) {
        NeighborSum neighborSum = new NeighborSum(new int[][]{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}});
        neighborSum.adjacentSum(1);
    }

    private int[][] grid;
    private Map<Integer, int[]> pos;
    /**
     * 三维整型数组，分别表示横纵坐标，和对角线
     */
    private final int[][][] dirs = {
            {{-1, 0}, {1, 0}, {0, -1}, {0, 1}},
            {{-1, -1}, {-1, 1}, {1, -1}, {1, 1}}
    };

    public NeighborSum(int[][] grid) {
        this.grid = grid;
        this.pos = new HashMap<>();
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                this.pos.put(grid[i][j], new int[]{i, j});
            }
        }
    }

    /**
     * 相邻总和
     * 返回在 grid 中与 value 相邻的元素之和，相邻指的是与 value 在上、左、右或下的元素。
     *
     * @param value 值
     * @return int
     */
    public int adjacentSum(int value) {
        return this.helper(value, 0);
    }

    /**
     * 返回在 grid 中与 value 对角线相邻的元素之和，对角线相邻指的是与 value 在左上、右上、左下或右下的元素。
     *
     * @param value 值
     * @return int
     */
    public int diagonalSum(int value) {
        return this.helper(value, 1);
    }

    private int helper(int value, int idx) {
        int[] ints = this.pos.get(value);
        int x = ints[0];
        int y = ints[1];
        int sum = 0;
        for (int[] dir : this.dirs[idx]) {
            if (x + dir[0] >= 0 && x + dir[0] < this.grid.length && y + dir[1] >= 0 && y + dir[1] < this.grid[0].length) {
                sum += this.grid[x + dir[0]][y + dir[1]];
            }
        }
        return sum;
    }

}
